package club.justwill.single.Service.impl;

import club.justwill.single.Service.ProjectsService;
import club.justwill.single.assembler.ProjectAssemble;
import club.justwill.single.bean.*;
import club.justwill.single.bean.Stick.DiscussProject;
import club.justwill.single.bean.Stick.ReplyDiscuss;
import club.justwill.single.helper.FileHelper;
import club.justwill.single.helper.ProjectHelp;
import club.justwill.single.impl.ToolsImpl;
import club.justwill.single.model.*;
import club.justwill.single.persistence.dao.*;
import club.justwill.single.persistence.document.*;
import club.justwill.single.persistence.jpo.*;
import club.justwill.single.persistence.store.ProjectHitsStore;
import club.justwill.single.persistence.store.ProjectSupportStore;
import club.justwill.single.persistence.store.StickStore;
import club.justwill.single.persistence.store.UserFollowProjectStore;
import club.justwill.single.util.JsonResponseHelper;
import club.justwill.single.util.ProjectHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by xiangnan on 15-12-26.
 */
@Service
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
public class ProjectsServiceImpl extends BaseService implements ProjectsService {

    @Autowired
    private UserDao userDao;

    @Autowired
    private ProjectDao projectDao;

    @Autowired
    private SkuDao skuDao;

    @Autowired
    private AgreementDao agreementDao;

    @Autowired
    private FileHelper fileHelper;

    @Autowired
    private ProjectSupportStore projectSupportStore;

    @Autowired
    private StickStore stickStore;

    @Autowired
    private ProjectAssemble projectAssemble;

    @Autowired
    private AuditDao auditDao;

    @Autowired
    private ProjectHitsStore projectHitsStore;

    @Autowired
    private UserFollowProjectStore userFollowProjectStore;
    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = true)
    public List<Projects> searchProjects(SearchProjects searchProjects, JsonResponse obj) {
        List<Projects> projectsList = null;
        if(searchProjects.getIndex()<0) {
            JsonResponseHelper.addError(obj, CoreConstants.INDEX_ERROR);
        } else if (searchProjects.getSize()<=0) {
            JsonResponseHelper.addError(obj, CoreConstants.SIZE_ERROR);
        } else {
            if(searchProjects.getStatus() == 50){
                projectsList=projectDao.getProjects(searchProjects.getIndex(), searchProjects.getSize());
            }else{
                projectsList = projectDao.searchProject(searchProjects.getIndex(), searchProjects.getSize(), searchProjects.getStatus());
            }
        }
        return projectsList;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = false)
    public Projects addProjects(SecurityToken token, CreateProject createProject, JsonResponse obj) {
        if(token.getUserType() == UserType.ANONYMOUS || token.getUserType() == UserType.INDIVIDUAL){
            JsonResponseHelper.addError(obj, CoreConstants.PROJECT_CREATE_ERROR);
        }
        if (ProjectHelper.canCreateProjects(createProject, obj)) {
            Projects projects = new Projects();
            projects.setUserId(token.getOperatorUserId());
            projects.setTitle(createProject.getTitle());
            projects.setAdvantage(createProject.getAdvantage());
            projects.setName(createProject.getName());
            projects.setFinancing(createProject.getFinancing());
            projects.setOverflow(createProject.getOverflow());
            projects.setEndTime(ToolsImpl.deserializeDate(createProject.getEndData()));
            projects.setTags(createProject.getTags());
            projects.setProvince(createProject.getProvince());
            projects.setCity(createProject.getCity());
            projects.setArea(createProject.getArea());
            projects.setStatus(ProjectType.STATUS_AUDITING);
            projects.setPublishTime(ToolsImpl.deserializeTimeStamp(createProject.getPublishTime()));
            projects.setModelId(createProject.getModelId());
            projects.setDispatchTime(ToolsImpl.deserializeDate(createProject.getDispatchTime()));
            projects.setType(0);
            projectDao.save(projects, token);

            Audit audit = new Audit();
            audit.setProjectId(projects.getProjectId());
            audit.setStatus(10);
            auditDao.save(audit,token);
            return projects;
        }
        return null;

    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = false)
    public void addAggrement(SecurityToken token, AddAgreement addAgreement, JsonResponse obj) {
        if (addAgreement == null) {
            JsonResponseHelper.addError(obj, CoreConstants.AGGREMENT_NOT_IS_NULL);
        }else if(addAgreement.getBonus()>1 || addAgreement.getService()>1){
            JsonResponseHelper.addError(obj, CoreConstants.SMALL_NUMBER_ERROR);
        }else if(addAgreement.getSettlement() < addAgreement.getCosting()){
            JsonResponseHelper.addError(obj, CoreConstants.SETT_AGREE_ERROR);
        }else {
            Projects projects = projectDao.getByProjectId(addAgreement.getProjectId());
            Agreement agreement = agreementDao.getByProjectId(addAgreement.getProjectId());
            User user = userDao.getById(token.getOperatorUserId());
            if(agreement != null){
                JsonResponseHelper.addError(obj, CoreConstants.PROJECT_AGREEMENT_EXIST);
            }else{
                agreement = new Agreement();
                if (projects == null || projects.getProjectId() == 0) {
                    JsonResponseHelper.addError(obj, CoreConstants.PROJECT_NOT_EXIST);
                } else if (user == null || user.getUserId() == 0) {
                    JsonResponseHelper.addError(obj, CoreConstants.USER_NOT_EXIST);
                } else if (addAgreement.getStartTime() == null || addAgreement.getStartTime().equals("") || addAgreement.getEndTime() == null || addAgreement.getEndTime().equals("")) {
                    JsonResponseHelper.addError(obj, CoreConstants.TIMESTAMP_NOT_IS_NULL);
                } else if(addAgreement.getService() > 1 || addAgreement.getBonus() > 1) {
                    JsonResponseHelper.addError(obj, CoreConstants.SERVICE_BONUS_IS_ERROR);
                } else {
                    try {
                        agreement.setStartTime(ToolsImpl.deserializeTimeStamp(addAgreement.getStartTime()));
                        agreement.setEndTime(ToolsImpl.deserializeTimeStamp(addAgreement.getEndTime()));
                        if(agreement.getStartTime().after(agreement.getEndTime())){
                            JsonResponseHelper.addError(obj, CoreConstants.ENDTIME_ERROR);
                            return;
                        }
                    } catch (Exception e) {
                        JsonResponseHelper.addError(obj, CoreConstants.TIMESTAMP_FORMAT_ERROR);
                        return;
                    }
                    agreement.setProjectId(addAgreement.getProjectId());
                    agreement.setUserId(token.getOperatorUserId());
                    agreement.setBonus(addAgreement.getBonus());
                    agreement.setCosting(addAgreement.getCosting());
                    agreement.setSale(addAgreement.getSale());
                    agreement.setService(addAgreement.getService());
                    agreement.setSettleMent(addAgreement.getSettlement());
                    agreementDao.save(agreement, token);
                }
            }
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = false)
    public Long addSKus(SecurityToken token, AddSKu addSKu, JsonResponse obj) {
        Projects projects = projectDao.getByProjectId(addSKu.getProjectId());
        if(projects == null) {
            JsonResponseHelper.addError(obj, CoreConstants.PROJECT_NOT_EXIST);
        } else {
            if(addSKu.getUnitPrice() < 0 || addSKu.getMaxPeople()<0 || addSKu.getDispatchPrice()<0) {
                JsonResponseHelper.addError(obj, CoreConstants.UP_MP_DP_OR_ERROR);
            }else{
                Skus skus = new Skus();
                skus.setProjectId(addSKu.getProjectId());
                skus.setName(addSKu.getName());
                skus.setUnitprice(addSKu.getUnitPrice());
                skus.setEarnings(addSKu.getEarnings());
                skus.setDispatchPrice(addSKu.getDispatchPrice());
                skus.setMaxPeople(addSKu.getMaxPeople());
               /* Set<Agreement> agreement = projects.getAgreement();
                if(agreement.iterator().hasNext()) {
                    Agreement agreement_item = agreement.iterator().next();
                    skus.setProfit((agreement_item.getSettleMent() - agreement_item.getCosting()) * agreement_item.getBonus() / projects.getMaxPeople());
                }*/
                skuDao.save(skus, token);
                return skus.getSkusId();

            }
        }
        return 0L;

    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = false)
    public void saveFile(SecurityToken token, JsonResponse obj, CommonsMultipartFile cover, Long projectId) {
        String path = fileHelper.saveFile(cover);
        if(path == null || "".equals(path)){
            JsonResponseHelper.addError(obj, CoreConstants.FILE_UPLOAD_FAILED);
        }else{
            Projects project = projectDao.getByProjectId(projectId);
            project.setCover(path);
            projectDao.update(project,token);
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = false)
    public ProjectSupport searchSupportInfo(long projectId, JsonResponse obj) {
        ProjectSupport projectSupport = projectSupportStore.searchProjectSupport(projectId);
        if(projectSupport == null){
            JsonResponseHelper.addError(obj, CoreConstants.SUPPORT_INFO_IS_NULL);
        }
        return projectSupport;
    }

    @Override
    public List<Stick> searchProjectStick(long projectId) {
        return stickStore.searchProjectComments(projectId);
    }

    @Override
    public Stick discuss(SecurityToken token, JsonResponse obj, DiscussProject discussProject) {
        Projects projects = projectDao.getByProjectId(discussProject.getProjectId());
        User user = userDao.getById(token.getOperatorUserId());
        if(projects == null) {
            JsonResponseHelper.addError(obj, CoreConstants.PROJECT_NOT_EXIST);
        } else if (user == null) {
            JsonResponseHelper.addError(obj, CoreConstants.PLEASE_LOGIN);
        } else {
            Stick stick = new Stick();
            stick.setUserId(token.getOperatorUserId());
            stick.setProjectId(projects.getProjectId());
            Comments comments = new Comments();
            comments.setComments(discussProject.getComment());
            comments.setUserName(user.getNickName());
            comments.setTime(ToolsImpl.deserializeDate(discussProject.getDate()));
            comments.setUserHeadIcon(user.getHeadIcon());
            stick.getProjectComments().add(comments);
            stickStore.save(stick);
            return stick;
        }
        return null;

    }

    @Override
    public Stick replyDiscuss(SecurityToken token, JsonResponse obj, ReplyDiscuss replyDiscuss) {
        User user = userDao.getById(token.getOperatorUserId());
        Stick stick = stickStore.getByStickId(replyDiscuss.getStickId());
        if (user == null) {
            JsonResponseHelper.addError(obj, CoreConstants.PLEASE_LOGIN);
        } else if (stick == null) {
            JsonResponseHelper.addError(obj, CoreConstants.STICK_ID_ERROR);
        } else {
            Comments comments = new Comments();
            comments.setComments(replyDiscuss.getComment());
            comments.setTime(ToolsImpl.deserializeDate(replyDiscuss.getDate()));
            comments.setUserName(user.getNickName());
            comments.setUserHeadIcon(user.getHeadIcon());
            stick.getProjectComments().add(comments);
            stickStore.save(stick);
            return stick;
        }
        return null;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = true)
    public ProjectsResp getProjectById(SecurityToken token, long projectId, JsonResponse obj) {
        Projects projects = projectDao.getByProjectId(projectId);
        ProjectHits projectHits = projectHitsStore.getById(projectId);
        if (projectHits == null) {
            projectHits = new ProjectHits();
            projectHits.setProjectId(projectId);
            projectHits.setProjectHits(0L);
        }
        projectHits.setProjectHits(projectHits.getProjectHits() + 1);
        projectHitsStore.save(projectHits);
        if(projects == null) {
            JsonResponseHelper.addError(obj,CoreConstants.PROJECT_NOT_EXIST);
            return null;
        } else {
            ProjectsResp projectsResp = projectAssemble.assembleProject(projects);
            projectsResp.setHits(String.valueOf(projectHits.getProjectHits()));

            UserFollowProject userFollowProject = userFollowProjectStore.searchFollowedProject(token.getOperatorUserId());
            if (userFollowProject == null) {
                projectsResp.setOverflow("UNFOLLOWED");
            } else {
                List<Long> list = userFollowProject.getFollowedProjectIdList();
                if (!ToolsImpl.isEmpty(list)) {
                    projectsResp.setOverflow("UNFOLLOWED");
                } else if (list.contains(projectId)) {
                    projectsResp.setOverflow("FOLLOWED");
                } else {
                    projectsResp.setOverflow("UNFOLLOWED");
                }
            }


            return projectsResp;
        }

    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = true)
    public List<ProjectsResp> getProjectByTagAndStatus(SecurityToken token, JsonResponse obj, GetProjectByTS getProjectByTS) {
        int tag = getProjectByTS.getTag();
        int status = getProjectByTS.getStatus();
        if (ProjectHelp.canSearchProject(obj, getProjectByTS)) {
            if (tag == ProjectType.TAG_ALL) {
                List<Projects> projectsList = projectDao.getProjectByStatus(status, getProjectByTS.getIndex(), getProjectByTS.getSize());
                return projectAssemble.assembleProjectMiniLisit(projectsList);
            }
            List<Projects> projectsList = projectDao.getProjectByTag(tag, status, getProjectByTS.getIndex(), getProjectByTS.getSize());
            if(!ToolsImpl.isEmpty(projectsList)) {
                return  projectAssemble.assembleProjectMiniLisit(projectsList);
            }
        }
        return new ArrayList<ProjectsResp>();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = false)
    public void updateProject(SecurityToken token, CreateProject updateProject, long projectId, JsonResponse obj) {
        Projects project = projectDao.getByProjectId(projectId);
        if (ProjectHelper.canCreateProjects(updateProject, obj)) {
            if(project == null){
                addProjects(token,updateProject,obj);
            }else{
                project.setUserId(token.getOperatorUserId());
                project.setTitle(updateProject.getTitle());
                project.setAdvantage(updateProject.getAdvantage());
                project.setName(updateProject.getName());
                project.setFinancing(updateProject.getFinancing());
                project.setOverflow(updateProject.getOverflow());
                project.setEndTime(ToolsImpl.deserializeDate(updateProject.getEndData()));
                project.setTags(updateProject.getTags());
                project.setProvince(updateProject.getProvince());
                project.setCity(updateProject.getCity());
                project.setArea(updateProject.getArea());
                project.setStatus(ProjectType.STATUS_AUDITING);
                project.setPublishTime(ToolsImpl.deserializeTimeStamp(updateProject.getPublishTime()));
                project.setModelId(updateProject.getModelId());
                project.setDispatchTime(ToolsImpl.deserializeDate(updateProject.getDispatchTime()));
                project.setType(0);
                projectDao.update(project,token);
            }
        }

    }
    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = false)
    public ProjectHits getProjectHits(JsonResponse obj, Long projectId) {
        ProjectHits projectHits = projectHitsStore.getById(projectId);
        if (projectHits == null) {
            projectHits = new ProjectHits();
            projectHits.setProjectId(projectId);
            projectHits.setProjectHits(0L);
        }
        return projectHits;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = false)
    public void addProjectsHits(JsonResponse obj, Long projectId) {
        ProjectHits projectHits = getProjectHits(obj, projectId);
        projectHitsStore.addHits(projectHits);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = false)
    public void updateSKus(SecurityToken token, UpdateSku updateSku, JsonResponse obj) {
        Skus skus = skuDao.getBySkuId(updateSku.getSkuId());
        if(skus!=null && skus.getSkusId()!=0){
            if(updateSku.getUnitPrice() < 0 || updateSku.getMaxPeople()<0 || updateSku.getDispatchPrice()<0) {
                JsonResponseHelper.addError(obj, CoreConstants.UP_MP_DP_OR_ERROR);
            }else{
                skus.setName(updateSku.getName());
                skus.setUnitprice(updateSku.getUnitPrice());
                skus.setEarnings(updateSku.getEarnings());
                skus.setDispatchPrice(updateSku.getDispatchPrice());
                skus.setMaxPeople(updateSku.getMaxPeople());
                skuDao.update(skus,token);
            }
        }
    }


}
